package l1j.server.server.datatables;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.DatabaseFactory;
import l1j.server.server.templates.L1Castle;
import l1j.server.server.utils.SQLUtil;

// Referenced classes of package l1j.server.server:
// IdFactory

public class CastleTable {

	private static Logger _log = Logger.getLogger(CastleTable.class.getName());

	private static CastleTable _instance;

	public static CastleTable getInstance() {
		if (_instance == null) {
			_instance = new CastleTable();
		}
		return _instance;
	}

	private final Map<Integer, L1Castle> _castles = new ConcurrentHashMap<Integer, L1Castle>();

	private CastleTable() {
		this.load();
	}

	public L1Castle getCastleTable(final int id) {
		return this._castles.get(id);
	}

	public L1Castle[] getCastleTableList() {
		return this._castles.values().toArray(new L1Castle[this._castles.size()]);
	}

	private void load() {
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("SELECT * FROM castle");

			rs = pstm.executeQuery();

			while (rs.next()) {
				final L1Castle castle = new L1Castle(rs.getInt(1), rs.getString(2));
				castle.setWarTime(this.timestampToCalendar((Timestamp) rs.getObject(3)));
				castle.setTaxRate(rs.getInt(4));
				castle.setPublicMoney(rs.getInt(5));
				castle.setCastleExp(rs.getInt("貢獻"));
				castle.setCastleLv(rs.getByte("等級"));
				castle.setSkillPoint(rs.getByte("技能點數"));
				castle._skillAtk = rs.getByte("狂暴打擊");
				castle._skillDef = rs.getByte("鋼鐵防禦");
				castle._skillDrop = rs.getByte("賞金獵人");
				castle._skillExp = rs.getByte("狩獵專長");
				this._castles.put(castle.getId(), castle);
				if(castle._skillAtk + castle._skillDef + castle._skillDrop + castle._skillExp > castle.getCastleLv()){
					castle._skillAtk = 0;
					castle._skillDef = 0;
					castle._skillDrop = 0;
					castle._skillExp = 0;
					castle.setSkillPoint(castle.getCastleLv());
				}
			}
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(rs);
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}

	public void resetCastleAllStat(final L1Castle castle){
		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("UPDATE castle SET 等級=?, 貢獻=?,技能點數=?, 狂暴打擊=?, 鋼鐵防禦=?, 賞金獵人=?, 狩獵專長=? WHERE castle_id=?");
			pstm.setByte(1, (byte) 0);
			pstm.setInt(2, 0);
			pstm.setByte(3,(byte) 0);
			pstm.setByte(4, (byte) 0);
			pstm.setByte(5, (byte) 0);
			pstm.setByte(6, (byte) 0);
			pstm.setByte(7, (byte) 0);
			pstm.setInt(8, castle.getId());
			pstm.execute();

//			_castles.put(castle.getId(), castle);
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}

	private Calendar timestampToCalendar(final Timestamp ts) {
		final Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(ts.getTime());
		return cal;
	}
	public void updateCastle(final L1Castle castle) {
		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("UPDATE castle SET name=?, war_time=?, tax_rate=?, public_money=? WHERE castle_id=?");
			pstm.setString(1, castle.getName());
			// XXX 攻城時間無法自動更新 by pigermin
			final SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			final String fm = sdf.format(castle.getWarTime().getTime());
			/*
			 * String fm = DateFormat.getDateTimeInstance().format(
			 * castle.getWarTime().getTime());
			 */
			pstm.setString(2, fm);
			pstm.setInt(3, castle.getTaxRate());
			pstm.setInt(4, castle.getPublicMoney());
			pstm.setInt(5, castle.getId());
			pstm.execute();

			this._castles.put(castle.getId(), castle);
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}
	public void updateCastleSkill(final L1Castle castle){
		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con
					.prepareStatement("UPDATE castle SET 技能點數=?, 狂暴打擊=?, 鋼鐵防禦=?, 賞金獵人=?, 狩獵專長=? WHERE castle_id=?");
			pstm.setByte(1, castle.getSkillPoint());
			pstm.setByte(2, castle.getSkillList()[1]);
			pstm.setByte(3, castle.getSkillList()[2]);
			pstm.setByte(4, castle.getSkillList()[3]);
			pstm.setByte(5, castle.getSkillList()[4]);
			pstm.setInt(6, castle.getId());
			pstm.execute();

//			_castles.put(castle.getId(), castle);
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}
	public void updateCastleStat(final L1Castle castle){
		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con
					.prepareStatement("UPDATE castle SET 等級=?, 貢獻=?, 技能點數=? WHERE castle_id=?");
			pstm.setByte(1, castle.getCastleLv());
			pstm.setInt(2, castle.getCastleExp());
			pstm.setByte(3, castle.getSkillPoint());
			pstm.setInt(4, castle.getId());
			pstm.execute();

	//		_castles.put(castle.getId(), castle);
		} catch (final SQLException e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}
}
